/*  Copyright 2011 Jason Jones
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.jasonwjones.hyperion.jessub.formattingvalue.date;

import org.joda.time.DateTime;

/**
 * Represents a particular adjustment to make to a date, such as rolling
 * the date back or forward by a certain number of days, months, or years.
 * @author jasonwjones
 *
 */
public class DateAdjustment {

	protected DateAdjustmentAspect adjustmentAsepect;
	protected int adjustmentValue;
	
	/**
	 * Is passed in one of the items from the NOW() tag, for example. The 
	 * delimiter is a colon, which is required.
	 * @param dateAdjustmentCode the unit to adjust by: typically one of DAYS,
	 * MONTHS, or YEARS, but technically is just anything in the DateAdjustmentAspect
	 * enumeration.
	 * @return a new DateAdjustment
	 */
	public static DateAdjustment createFrom(String dateAdjustmentCode) {
		String[] components = dateAdjustmentCode.split(":");
		
		DateAdjustmentAspect adjustmentAspect = DateAdjustmentAspect.valueOf(components[0].trim());
		
		int adjustValue = 0;
		
		try {
			adjustValue = Integer.valueOf(components[1]);
		} catch (Exception e) {
			System.err.println("Warning: Error reading numeric date adjustment value (leaving as 0): " + e.getMessage());
		}
		
		return new DateAdjustment(adjustmentAspect, adjustValue);
	}
	
	/**
	 * Constructor is private because it is only called by one of our own
	 * static initializers.
	 * @param adjustmentAspect the adjustment aspect (such as days or months)
	 * @param adjustmentValue the amount of the time unit (1 month, -2 days, etc)
	 */
	private DateAdjustment(DateAdjustmentAspect adjustmentAspect, int adjustmentValue) {
		this.adjustmentAsepect = adjustmentAspect;
		this.adjustmentValue = adjustmentValue;
	}
	
	/**
	 * Sets the adjustment value
	 * @param adjustmentValue 
	 */
	public void setAdjustmentValue(int adjustmentValue) {
		this.adjustmentValue = adjustmentValue;
	}
	
	/**
	 * Generates a new DateTime by applying our unit and amount to a passed
	 * in DateTime
	 * @param dateTime the DateTime to adjust
	 * @return a new DateTime with the adjustment added
	 */
	public DateTime applyTo(DateTime dateTime) {
		switch (adjustmentAsepect) {
		case DAYS:
			return dateTime.plusDays(adjustmentValue);
		case MONTHS:
			return dateTime.plusMonths(adjustmentValue);
		case YEARS:
			return dateTime.plusYears(adjustmentValue);
		}
		return dateTime;
	}
	
	/**
	 * Simple print value
	 */
	@Override
	public String toString() {
		String format = "%s %d %s";
		
		String direction = (adjustmentValue < 0 ? "back" : "forward");
		int amount = Math.abs(adjustmentValue);
		String unit = adjustmentAsepect.toString();
		
		return String.format(format, direction, amount, unit);
	}
	
}
